﻿/*************************************************************************
 *    分部过滤执行器
 *    
 *   author:jinshuai
 *   email:redfox2008@126.com
 *   date:2016-05-12 
 *   blog:red-fox.cnblogs.com
 * 
 ***********************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;

namespace FilterRunner
{

    /// <summary>
    /// 分部过滤执行器
    /// </summary>
    /// <typeparam name="T">处理的对像类型 </typeparam>
    public class Runner<T>
    {
        protected T _targetObj = default(T);

        //执行对像
        protected readonly Func<T,RunnerMessage> Executor = null;

        /// <summary>
        /// 过滤器
        /// </summary>
        public List<IRunnerFilter<T>> Filters = new List<IRunnerFilter<T>>();


        /// <summary>
        /// 构造
        /// </summary>
        /// <param name="obj">要处理的对像</param>
        /// <param name="runner"></param>
        public Runner(T obj, Func<T,RunnerMessage> runner)
        {
            _targetObj = obj;
            Executor = runner;
        }



        /// <summary>
        /// 运行
        /// </summary>
        /// <returns></returns>
        public virtual RunnerMessage Run()
        {
            var isContinueRunNext = true;
            var result = RunFilters(out isContinueRunNext);

            if (isContinueRunNext == false)
            {
                return result;
            }

            if (Executor == null)
            {
                throw new Exception("Runner is Null ! ");
            }

            return Executor(_targetObj);
        }


        /// <summary>
        /// 运行所有的 Filter
        /// </summary>
        /// <param name="isContinueRunNext"></param>
        /// <returns></returns>
        protected virtual RunnerMessage RunFilters(out bool isContinueRunNext)
        {
            isContinueRunNext = true;

            if (Filters == null || Filters.Count <= 0)
            {
                return null;
            }

            RunnerMessage result = null;

            Filters = Filters.Where(filter => filter != null).OrderBy(p => p.Sequence).ToList();

            foreach (var filter in Filters)
            {
                result = filter.Run(this._targetObj, out isContinueRunNext);

                //如果不用继续运行了就跳出
                if (false == isContinueRunNext)
                {
                    return result;
                }
            }

            return result;

        }

    }
}
